package com.ihealthway.all.slog.interceptor;

import com.ihealthway.all.slog.annotation.SLog;
import com.ihealthway.all.groupbuy.services.AdminLogService;
import com.ihealthway.all.groupbuy.vo.AdminLog;
import com.ihealthway.all.groupbuy.vo.SysAdmin;
import com.ihealthway.all.commons.Constants;
import org.nutz.aop.InterceptorChain;
import org.nutz.aop.MethodInterceptor;
import org.nutz.el.El;
import org.nutz.ioc.Ioc;
import org.nutz.lang.Lang;
import org.nutz.lang.segment.CharSegment;
import org.nutz.lang.util.Context;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.Mvcs;

import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Implement interceptor for handle log info
 * @author 凡梦星尘(elkan1788@gmail.com)
 */
public class SLogAopInterceptor implements MethodInterceptor {

    private static final Log logger = Logs.get();

    protected AdminLogService operateLogService;

    protected String remarks;
    protected String module;
    protected String operateType;
    protected CharSegment content;
    protected Map<String, El> els = new HashMap<>();

    public SLogAopInterceptor(Ioc ioc, SLog slog, Method method) {

        this.content = new CharSegment(slog.content());
        if (content.hasKey()) {
            els.clear();
            for (String key : content.keys()) {
                els.put(key, new El(key));
            }
        }
        this.operateLogService = ioc.get(AdminLogService.class);
        this.remarks = method.getDeclaringClass().getName() + "#" + method.getName();
        this.module = slog.module();
        this.operateType = slog.type();
    }

    public void filter(InterceptorChain chain) throws Throwable {
        try {
            chain.doChain();
            String _content;
            if (content.hasKey()) {
                Context ctx = Lang.context();
                ctx.set("args", chain.getArgs());
                ctx.set("req", Mvcs.getReq());
                ctx.set("return", chain.getReturn());
                Context _ctx = Lang.context();
                for (String key : content.keys()) {
                    _ctx.set(key, els.get(key).eval(ctx));
                }
                _content = content.render(_ctx).toString();
            } else {
                _content = content.getOrginalString();
            }

            HttpSession session = Mvcs.getHttpSession(false);
            SysAdmin sysAdmin = (SysAdmin) session.getAttribute(Constants.ADMIN_LOGIN_SESSION);

            AdminLog operateLog = new AdminLog();
            operateLog.setSaId(sysAdmin.getAdminId());
            operateLog.setModule(this.module);
            operateLog.setOperateType(this.operateType);
            operateLog.setContent(_content);
            operateLog.setIpAddr(Lang.getIP(Mvcs.getReq()));
            operateLog.setRemarks(this.remarks);
            operateLog.setCreateTime(new Date());
            this.operateLogService.asyncLog(operateLog);
        } catch (Throwable e) {
           logger.error("Save admin operate log failed.", e);
        }
    }

}
